package toolkit.tianshi.excelpoi.serviceimpl;

import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Maps;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import toolkit.tianshi.common.time.DateHelper;
import toolkit.tianshi.common.excelpoi.AnalyzeModel;
import toolkit.tianshi.excelpoi.service.ProduceService;


/**
 * @author zhangLin
 */
public class ProduceServiceImpl implements ProduceService{

    private final LoadingCache<Class, Map<String,PropertyDescriptor>> produceCache =
            CacheBuilder.newBuilder().build(new CacheLoader<Class, Map<String, PropertyDescriptor>>() {
                @Override
                public Map<String, PropertyDescriptor> load(Class key) throws Exception {
                    Field[] fields = key.getDeclaredFields();
                    Map<String, PropertyDescriptor> map = Maps.newHashMap();
                    for (Field field: fields) {
                        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), key);
                        map.put(field.getName(), propertyDescriptor);
                    }
                    return map;
                }
            });

    @Override
    public void produceTitle(Sheet sheet  , Integer startLine, AnalyzeModel analyzeModel, Map<String, String> title) {
        List<AnalyzeModel.Site> tableTitle = analyzeModel.getTableTitle();
        if (!tableTitle.isEmpty() && title!=null) {
            for (AnalyzeModel.Site site : tableTitle) {
                Row row = sheet.getRow(site.getRow());
                if (row == null) {
                    row = sheet.createRow(site.getRow());
                }
                Cell cell = row.getCell(site.getColumn());
                if (cell == null) {
                    cell = row.createCell(site.getColumn());
                }
                cell.setCellType(CellType.STRING);
                cell.setCellValue(Strings.nullToEmpty(title.get(site.getContent())));
            }
        }
        while (sheet.getLastRowNum() >= startLine) {
            sheet.shiftRows(startLine + 1,sheet.getLastRowNum() + 1,-1);
        }

    }

    @Override
    public synchronized Integer produceExcel
            (Sheet sheet  , Integer startLine, AnalyzeModel analyzeModel, List<Object> datas) throws InvocationTargetException, IllegalAccessException {
        System.out.println("startLine:" + startLine + "time:" + DateHelper.getCurrentTimess());
        if (!datas.isEmpty()) {
            List<AnalyzeModel.Site> content = analyzeModel.getContent();
            Map<String, PropertyDescriptor> proMap = produceCache.getUnchecked(datas.get(0).getClass());
            for (Object data : datas) {
                Row row = sheet.getRow(startLine);
                if (row == null) {
                    row = sheet.createRow(startLine);
                }
                for (AnalyzeModel.Site site : content) {
                    Cell cell = row.getCell(site.getColumn());
                    if (cell == null) {
                        cell = row.createCell(site.getColumn());
                    }
                    cell.setCellType(CellType.STRING);
                    if ( "id".equals(site.getContent())) {
                        /**
                         * 序号
                         */
                        cell.setCellValue(String.valueOf(startLine - analyzeModel.getInitialRow() + 1));
                    } else {
                        cell.setCellValue(String.valueOf(proMap.get(site.getContent()).getReadMethod().invoke(data)));
                    }
                }
                startLine++;
            }
        }
        return startLine;
    }
}
